package ru.maxmatveev.dyndao.demo;

import org.hibernate.SessionFactory;
import org.hibernate.Criteria;
import org.hibernate.QueryException;
import org.hibernate.criterion.Restrictions;
import org.hibernate.cfg.AnnotationConfiguration;
import ru.maxmatveev.dyndao.Ordering;
import ru.maxmatveev.dyndao.Pagination;
import ru.maxmatveev.dyndao.Restriction;
import ru.maxmatveev.dyndao.demo.dao.ComplexDao;
import ru.maxmatveev.dyndao.demo.dao.ParentDao;
import ru.maxmatveev.dyndao.demo.dao.SimpleEntityDao;
import ru.maxmatveev.dyndao.demo.dao.ADao;
import ru.maxmatveev.dyndao.demo.model.*;
import ru.maxmatveev.dyndao.impl.hibernate.DaoFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.Date;

/**
 * @author Max Matveev
 *         Date: Jan 4, 2009
 *         Time: 4:06:09 PM
 */
public class Test {
    public static void main(String[] args) {
        SessionFactory sessionFactory = new AnnotationConfiguration()
                .addAnnotatedClass(SomeEntity.class)
                .addAnnotatedClass(Parent.class)
                .addAnnotatedClass(Child.class)
                .addAnnotatedClass(A.class)
                .addAnnotatedClass(B.class)
                .addAnnotatedClass(C.class)
                .setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver")
                .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:.")
                .setProperty("hibernate.connection.username", "sa")
                .setProperty("hibernate.connection.password", "")
                .setProperty("hibernate.connection.useUnicode", "true")
                .setProperty("hibernate.connection.characterEncoding", "UTF-8")
                .setProperty("hibernate.connection.charSet", "UTF-8")
                .setProperty("hibernate.dialect",
                        "org.hibernate.dialect.HSQLDialect")
                .setProperty("hibernate.show_sql", "true")
                .setProperty("hibernate.hbm2ddl.auto", "create-drop")
                .setProperty("hibernate.current_session_context_class", "thread")
                .buildSessionFactory();

        sessionFactory.getCurrentSession().beginTransaction();

        SimpleEntityDao simpleDao = (SimpleEntityDao) DaoFactory.getInstance(SimpleEntityDao.class, SomeEntity.class, sessionFactory);
        ADao aDao = (ADao) DaoFactory.getInstance(ADao.class, A.class, sessionFactory);
        List<SomeEntity> simpleEntities = new ArrayList<SomeEntity>();
        System.out.println("+++Generating simple entities; checking save()");
        for (int i = 0; i < 20; i++) {
            SomeEntity entity = new SomeEntity();
            entity.setValue1("value 1 " + i);
            entity.setValue2("value 2 " + (i % 5));
            simpleEntities.add(entity);
            simpleDao.save(entity);
        }
        System.out.println("+++Flushing session");
        sessionFactory.getCurrentSession().flush();

        System.out.println("+++Checking getAll()");
        int count = simpleDao.getAll().size();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 20) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }

        List<SomeEntity> entities = simpleDao.findByIds(Arrays.asList(1L,3L,5L,7L));
        System.out.println("+++Checking getById()");
        SomeEntity reference = simpleEntities.get(10);
        SomeEntity test = simpleDao.getById(reference.getId());
        SomeEntity test2 = simpleDao.getById(reference.getId() + 1);
        SomeEntity test3 = simpleDao.getById(-1L);
        if (reference.equals(test) && !reference.equals(test2) && test3 == null) {
            System.out.println("+++Ok");
        } else {
            System.out.println("+++Failed");
        }

        System.out.println("+++Checking delete()");
        simpleDao.delete(reference);
        sessionFactory.getCurrentSession().flush();
        if (simpleDao.getById(reference.getId()) == null) {
            System.out.println("+++Ok");
        } else {
            System.out.println("+++Failed");
        }

        System.out.println("+++Checking getCount()");
        count = simpleDao.getCount();
        if (count == 19) {
            System.out.println("+++Ok");
        } else {
            System.out.println("+++Failed");
        }

        System.out.println("+++Checking getOrderedByField()");
        count = simpleDao.getOrderedByField().size();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 19) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }

        System.out.println("+++Checking getOrderedByCriteria()");
        count = simpleDao.getOrderedByCriteria(new Ordering("value2", Ordering.Direction.DESC).Order("value1")).size();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 19) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }

        System.out.println("+++Checking getPaginated()");
        count = simpleDao.getPaginated(new Pagination(6, 7)).size();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 7) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }

        System.out.println("+++Checking getFilteredByField()");
        count = simpleDao.getFilteredByField("uE 2 2").size();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 4) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }

        System.out.println("+++Checking getFilteredByCriteria()");
        count = simpleDao.getFilteredByCriteria(Restriction.or(Restriction.ieq("value1", "vaLue 1 1"), Restriction.eq("value2", "value 2 2"))).size();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 5) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }

        System.out.println("+++Checking getPaginatedFilteredByCriteriaOrderedByCriteria()");
        count = simpleDao.getPaginatedFilteredByCriteriaOrderedByCriteria(new Pagination(6, 7), Restriction.or(Restriction.ilike("value1", "vaLue 1"), Restriction.like("value2", "value 2")), new Ordering("value2", Ordering.Direction.DESC).Order("value1")).size();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 7) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }

        System.out.println("+++Checking getCountFilteredByCriteria()");
        count = simpleDao.getCountFilteredByCriteria(Restriction.or(Restriction.ieq("value1", "vaLue 1 1"), Restriction.eq("value2", "value 2 2")));
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 5) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }

        System.out.println("+++Checking getCountPredefined()");
        count = simpleDao.getCountPredefined();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 5) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }



        System.out.println("________________________________________");
        System.out.println("+++HQL tests");

        System.out.println("+++Checking updateById()");
        simpleDao.updateById("UPDATED", simpleEntities.get(3).getId());
        System.out.println("+++Ok");

        System.out.println("+++Checking getWithHqlById()");
        test = simpleDao.getWithHqlById(simpleEntities.get(8).getId());
        if (test.equals(simpleEntities.get(8))) {
            System.out.println("+++Ok");
        } else {
            System.out.println("+++Checking failed");
        }

        System.out.println("+++Checking getOrderedByCriteria()");
        count = simpleDao.getAllWithHql().size();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 19) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }



        System.out.println("________________________________________");
        System.out.println("+++Complex tests");
        ComplexDao childDao = (ComplexDao) DaoFactory.getInstance(ComplexDao.class, Child.class, sessionFactory);
        ParentDao parentDao = (ParentDao) DaoFactory.getInstance(ParentDao.class, Parent.class, sessionFactory);
        System.out.println("+++Populating DB");
        List<Child> children = new ArrayList<Child>();
        List<Parent> parents = new ArrayList<Parent>();
        for (int i = 0; i < 3; i++) {
            Parent parent = new Parent();
            parent.setName("parentName_" + i);
            parents.add(parent);
            parentDao.save(parent);
        }
        for (int i = 0; i < 30; i++) {
            Child child = new Child();
            child.setName("childName_" + (i % 5) + "_" + i);
            children.add(child);
            childDao.save(child);
            switch (i % 7) {
                case 0:
                    parents.get(0).getChildren().add(child);
                    break;
                case 1:
                    parents.get(1).getChildren().add(child);
                    break;
                case 2:
                    parents.get(2).getChildren().add(child);
                    break;
                case 3:
                    parents.get(0).getChildren().add(child);
                    parents.get(1).getChildren().add(child);
                    break;
                case 4:
                    parents.get(0).getChildren().add(child);
                    parents.get(2).getChildren().add(child);
                    break;
                case 5:
                    parents.get(1).getChildren().add(child);
                    parents.get(2).getChildren().add(child);
                    break;
                case 6:
                    parents.get(0).getChildren().add(child);
                    parents.get(1).getChildren().add(child);
                    parents.get(2).getChildren().add(child);
                    break;
            }
        }
        System.out.println("+++Flushing session");
        sessionFactory.getCurrentSession().flush();

        System.out.println("+++Checking getByParentId()");
        List<Child> tempCL = childDao.getByParentId(parents.get(0).getId());
        count = tempCL.size();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 17) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }

        System.out.println("+++Checking getByParentField()");
        tempCL = childDao.getByParentField("TName_2");
        count = tempCL.size();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 16) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }

        System.out.println("+++Checking getByParentRestriction()");
        tempCL = childDao.getByParentRestriction(Restriction.not(Restriction.eq("id", parents.get(0).getId())));
        count = tempCL.size();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 25) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }


        System.out.println("+++Checking getCountByParentId()");
        count = childDao.getCountByParentId(parents.get(0).getId());
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 17) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }

        System.out.println("+++Checking getCountByParentField()");
        count = childDao.getCountByParentField("TName_2");
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 16) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }

        System.out.println("+++Checking getCountByParentRestriction()");
        count = childDao.getCountByParentRestriction(Restriction.not(Restriction.eq("id", parents.get(0).getId())));
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 25) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }


        System.out.println("+++Checking getPaginatedAndOrderedByCriteriaAndFilteredByParentRestrictionAndFilteredByRestriction()");
        tempCL = childDao.getPaginatedAndOrderedByCriteriaAndFilteredByParentRestrictionAndFilteredByRestriction(
                Restriction.not(Restriction.eq("id", parents.get(0).getId())),
                new Ordering("name"),
                Restriction.ilike("name", "child"),
                new Pagination(7, 8)
        );
        count = tempCL.size();
        System.out.println(String.format("+++Got %d entities", count));
        if (count != 8) {
            System.out.println("+++Checking failed");
        } else {
            System.out.println("+++Ok");
        }
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(A.class);
        criteria.add(Restrictions.ilike("p.name", "qwer"));
            criteria.createAlias("parent.parent", "p");
        System.out.println(criteria.list());
        System.out.println("_______________");
        aDao.get(Restriction.ilike("parent.name", "qwer"));
        aDao.get(Restriction.and(Restriction.or(Restriction.gt("date", new Date()), Restriction.lt("date", new Date())), Restriction.ge("date", new Date())));
        sessionFactory.getCurrentSession().getTransaction().commit();
        sessionFactory.getCurrentSession().close();
    }
}
